package speed2010.andreza.vspeed.util;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
 */
public final class ReflectionUtils {

	private ReflectionUtils() {
	}

	public static Class<?> getParameterType(final Object instance, final int parameterIndex) {
		final Class<?> testClass = instance.getClass();

		final List<Type> typesToTest = new ArrayList<Type>();
		typesToTest.add(testClass.getGenericSuperclass());
		typesToTest.addAll(Arrays.asList(testClass.getGenericInterfaces()));

		for (final Type currentType : typesToTest) {
			if (currentType instanceof ParameterizedType) {
				final ParameterizedType pType = (ParameterizedType) currentType;
				final Type nThType = pType.getActualTypeArguments()[parameterIndex];

				Class<?> whatWeWant = null;
				if (nThType instanceof Class) {
					whatWeWant = (Class<?>) nThType;
				} else if (nThType instanceof ParameterizedType) {
					whatWeWant = (Class<?>) ((ParameterizedType) nThType).getRawType();
				}

				return whatWeWant;
			}
		}

		return null;
	}

	public static void setBigField(final Object pObject, final Object pValueToSetOnBigField,
			final Object pValueToSetOnSmallField, final String pBigFieldName, final String pSmallFieldName,
			final boolean pCondition) throws Exception {
		if (pObject == null) {
			return;
		}

		final Method vMethodBig = pObject.getClass().getMethod("set" + pBigFieldName, pValueToSetOnBigField.getClass());
		final Method vMethodSmall = pObject.getClass().getMethod("set" + pSmallFieldName,
				pValueToSetOnBigField.getClass());

		if (pCondition) {
			vMethodSmall.invoke(pObject, pValueToSetOnSmallField);
			vMethodBig.invoke(pObject, pValueToSetOnBigField);
		} else {
			vMethodBig.invoke(pObject, (Object) null);
			vMethodSmall.invoke(pObject, pValueToSetOnBigField);
		}
	}

}